\section{\texttt{vim}编辑器}

\subsection{完成完成\texttt{vimtutor}}
\begin{questionbox}
完成 vimtutor。备注：它在一个 80x24（80 列，24 行） 终端窗口看起来效果最好。
\end{questionbox}
首先我们了解一下，什么是\texttt{vimtutor}？
vimtutor 是 \texttt{vim} 编辑器自带的一个交互式教学脚本，它：
\begin{itemize}
    \item 不会修改任何配置
    \item 以 \texttt{vim} 模式教你使用基础命令
    \item 全程在终端中运行
    \item 约 25–30 分钟可完成
\end{itemize}

我们在\texttt{bash}中输入\texttt{vimtutor}命令开始练习，具体结果如下图\ref{vimtutor练习}。\\

\texttt{vim}中各个命令的作用：
\begin{enumerate}
    \item 基本移动：h j k l，进入/退出插入模式 i / Esc
    \item 删除：x（删字符）、dw（删词）、dd（删行）
    \item 撤销：u（撤销）、U（恢复整行）
    \item 定位：w（跳词）、b（回跳词）、0 / \$（行首/行尾）
    \item 查找：f<char>（行内找）、/text（向下搜）、?text（向上搜）
    \item 替换：r（替换字符）、R（连续替换）、cw（改词）
    \item 复制粘贴：yy（复制行）、p（粘贴）、P（前粘）
    \item 命令模式：:w（保存）、:q（退出）、:help（查帮助）
\end{enumerate}

\begin{figure}[H]]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 173221.png}
	\caption{vimtutor练习}
	\label{vimtutor练习}
\end{figure}

\subsection{更改\texttt{vim}设置并查看区别}
\begin{questionbox}
    下载我们提供的\texttt{vimrc}，然后把它保存到\texttt{~/.vimrc}。通读这个注释详细的文件（用 \texttt{vim}!）， 然后观察 \texttt{vim} 在这个新的设置下看起来和使用起来有哪些细微的区别。
\end{questionbox}

我们首先将文件下载到D盘（因为这里我的浏览器的默认下载地址是D盘），由于我们使用的Linux子系统（WSL），所以我们可以通过如下命令将文件复制到Linux子系统中
\begin{lstlisting}
cp /mnt/d/vimrc ~/.vimrc #d/vimrc是文件在Windows系统中的位置，~/.vimrc是我们希望文件在Linux子系统中的位置
\end{lstlisting}

由于在子系统中的位置是~/.vimrc（隐藏文件），所以我们通过\texttt{ls -a -t}（显示所有文件并按时间顺序排列），发现该文件成功添加子系统中，具体操作如图\ref{下载vimrc文件并复制到子系统中}。接着我们通过\texttt{vim .vimrc}命令查看该文件内容，内容如图\ref{vimrc具体内容}。
\begin{figure}[htb]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 180410.png}
	\caption{下载vimrc文件并复制到子系统中}
	\label{下载vimrc文件并复制到子系统中}
\end{figure}

通过查看文档和询问AI，我们发现了如下的更改：
\begin{description}
    \item[\texttt{set nocompatible}] 
    禁用 Vi 兼容模式，启用 \texttt{vim} 的现代功能（如多级撤销、语法高亮等），确保使用 Vim 的全部特性。

    \item[\texttt{syntax on}] 
    开启语法高亮功能。不同语言的关键字、字符串、注释等将以不同颜色显示，显著提升代码可读性。

    \item[\texttt{set shortmess+=I}] 
    抑制 \texttt{vim} 启动时的默认欢迎信息，使编辑器直接进入编辑状态，减少干扰。

    \item[\texttt{set number}] 
    显示行号。每行左侧显示其实际行号，便于定位和引用。

    \item[\texttt{set relativenumber}] 
    启用相对行号。当前行显示实际行号，其他行显示相对于当前行的行数差，方便使用 \texttt{10j}、\texttt{5k} 等命令快速跳转。

    \item[\texttt{set laststatus=2}] 
    始终显示状态栏，即使只有一个窗口。状态栏提供模式、文件名、光标位置等信息，增强上下文感知。

    \item[\texttt{set backspace=indent,eol,start}] 
    放宽退格键的限制，允许在插入模式下删除缩进、行尾和插入起始点前的字符，提升编辑流畅性。

    \item[\texttt{set hidden}] 
    允许隐藏未保存的缓冲区。可以在不保存的情况下切换文件，避免因 \texttt{:q} 而中断工作流。

    \item[\texttt{set ignorecase smartcase}] 
    搜索时忽略大小写，但如果搜索词中包含大写字母，则变为区分大小写。兼顾灵活性与精确性。

    \item[\texttt{set incsearch}] 
    启用增量搜索。输入搜索命令时实时高亮匹配项，便于快速定位目标。

    \item[\texttt{nmap Q <Nop>}] 
    禁用默认的 \texttt{Q} 命令（进入 Ex 模式），防止误操作，推荐使用 \texttt{gq} 进行文本格式化。

    \item[\texttt{set noerrorbells visualbell t\_vb=}] 
    禁用声音提示（蜂鸣），改用视觉提示（屏幕闪烁），减少听觉干扰，适合安静环境。

    \item[\texttt{set mouse=a}] 
    启用鼠标支持，可在所有模式下使用鼠标选择、滚动和点击。虽然推荐使用键盘，但对初学者或混合操作很有帮助。

    \item[箭头键映射] 
    以下映射在普通模式和插入模式下阻止使用箭头键，并提示用户使用 \texttt{hjkl} 进行移动：
    \begin{verbatim}
nnoremap <Left> :echoe "Use h"<CR>
nnoremap <Right> :echoe "Use l"<CR>
nnoremap <Up> :echoe "Use k"<CR>
nnoremap <Down> :echoe "Use j"<CR>
inoremap <Left> <ESC>:echoe "Use h"<CR>
inoremap <Right> <ESC>:echoe "Use l"<CR>
inoremap <Up> <ESC>:echoe "Use k"<CR>
inoremap <Down> <ESC>:echoe "Use j"<CR>
    \end{verbatim}
\end{description}

\begin{figure}[H]
	\centering
	\includegraphics[width=0.8\linewidth]{assets/images/QQ截图20250907180812.png}
	\caption{vimrc具体内容}
	\label{vimrc具体内容}
\end{figure}

\subsection{配置 \texttt{vim} 快速文件搜索：使用 \texttt{CtrlP} 插件}
\begin{questionbox}
    安装和配置一个插件： \texttt{CtrlP}.vim.
\begin{enumerate}
\item 用 \texttt{mkdir -p ~/.vim/pack/vendor/start} 创建插件文件夹
\item 下载这个插件：
\begin{lstlisting}
cd ~/.vim/pack/vendor/start
git clone https://github.com/ctrlvim/ctrlp.vim
\end{lstlisting}
\item 阅读这个插件的文档。尝试用 \texttt{CtrlP} 来在一个工程文件夹里定位一个文件，打开 \texttt{vim}, 然后用 \texttt{vim} 命令控制行开始:\texttt{CtrlP}.
\item 自定义 \texttt{CtrlP}：添加 configuration 到你的 ~/.vimrc 来用按 Ctrl-P 打开 \texttt{CtrlP}
\end{enumerate}
\end{questionbox}

为了解决这个问题，我们首先需要，下载和安装插件,在\texttt{bash}中输入下面的命令：
\begin{lstlisting}
mkdir -p ~/.vim/pack/vendor/start  #创建插件目录
cd ~/.vim/pack/vendor/start        #下载插件
git clone https://github.com/ctrlvim/ctrlp.vim
\end{lstlisting}
具体过程如图\ref{下载安装插件}
\begin{figure}[htb]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 195255.png}
	\caption{下载安装插件}
	\label{下载安装插件}
\end{figure}

接着我们需要配置我们的快捷键，分为下面两步：
\begin{enumerate}
    \item 打开\texttt{vim}配置文件，\texttt{vim ~/.vimrc}
    \item 将下面的代码输入到文件末尾
\begin{lstlisting}
" 启用 CtrlP 插件并设置快捷键
let g:ctrlp_map = '<c-p>'
let g:ctrlp_cmd = 'CtrlP'

" 可选：优化 CtrlP 搜索行为
let g:ctrlp_use_caching = 1        " 启用缓存，加快搜索
let g:ctrlp_match_window = 'bottom,order:btt,min:1,max:20'  " 显示匹配结果
\end{lstlisting}
\end{enumerate}

接着我们就需要验证我们的快捷键是否配置成功，分为下面几个步骤;
\begin{enumerate}
    \item 在项目根目录打开
    \begin{lstlisting}
    vim
    \end{lstlisting}
    \item 按下 Ctrl+P（即 Ctrl 键 + P 键）
    \item 输入文件名的一部分（比如 read）
    \item CtrlP 会模糊匹配项目中的文件，用 ↑↓ 选择，Enter 打开
    \item 如果弹出一个搜索框，并列出项目中的文件 → 成功！
\end{enumerate}

结果如下图\ref{ctrlp快捷键效果}
\begin{figure}[htb]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 200839.png}
	\caption{ctrlp快捷键效果}
	\label{ctrlp快捷键效果}
\end{figure}

由图\ref{ctrlp快捷键效果}可知，实验结果符合我们的预期

\subsection{进阶：将XML文件转化为Json文件}
\begin{questionbox}
    （高阶）用 Vim 宏将 XML 转换到 JSON (例子文件)。 尝试着先完全自己做，但是在你卡住的时候可以查看上面 宏 章节。
\end{questionbox}

我们第一步是下载好我们的示例文件，输入下面的命令：
\begin{lstlisting}
    wget https://missing-semester-cn.github.io/2020/files/example-data.xml -O example-data.xml
\end{lstlisting}
具体操作如图\ref{下载示例文件}
\begin{figure}[htb]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 202617.png}
	\caption{下载示例文件}
	\label{下载示例文件}
\end{figure}

接着正式开始我们的练习：
\begin{enumerate}
    \item 清理文件，只保留数据条目:进入命令模式，删除不必要的标签和空行，只保留 <person> 标签内的内容：
\begin{lstlisting}
:%s/^\s*<people>\|<\/people>//g
:%s/^\s*<person>\|<\/person>//g
:%s/^\s*$//g
\end{lstlisting}
    \item 将每个 <person> 块转换为一行，并删除所有空格:在命令模式中输入如下内容
\begin{lstlisting}
:%s/\n\+/\r/g
:g/^\s*$/d
\end{lstlisting}
    \item 替换标签为\texttt{JSON}字段\\
    处理\texttt{<name>}标签:
\begin{lstlisting}
:%s/<name>\([^<]*\)<\/name>/"name": "\1",/
\end{lstlisting}
    处理 <email> 标签
\begin{lstlisting}
:%s/<email>\([^<]*\)<\/email>/"email": "\1",/
\end{lstlisting}
\item 包裹成 JSON 对象:
我们需要在每条记录的开头添加 {，结尾添加 }。
\begin{lstlisting}
:%s/^/{ /
:%s/$/ }/
\end{lstlisting}
\item  删除多余的逗号:
由于我们在处理\texttt{<name>}和\texttt{<email>}标签时都添加了逗号，所以需要删除多余的逗号。
\begin{lstlisting}
:%s/,\s*}/}/g
\end{lstlisting}
\item 包装成 JSON 数组:在文件开头添加 [，在文件末尾添加 ],在每行末尾添加逗号（除了最后一行）
\begin{lstlisting}
:1i[<CR>
:$a]<Esc>
:1,$-1s/$/,/
\end{lstlisting}
\end{enumerate}

经过上面的处理后我们的文件变成了如下格式，如图\ref{JSON格式文件}
\begin{figure}[htb]
	\centering
	\includegraphics[width=\linewidth]{assets/images/屏幕截图 2025-09-07 222953.png}
	\caption{JSON格式文件}
	\label{JSON格式文件}
\end{figure}

上面的过程太复杂了，为了每次方便我们进行转换，我们可以把上面命令编写成一个\texttt{vim}脚本，首先使用\texttt{vim xml2json.vim}命令新建并编辑脚本，然后在脚本中输入下面的内容：
\begin{lstlisting}
:%s/<name>\([^<]*\)<\/name>/"name": "\1",/
:%s/^/{ /
:%s/$/ }/
:%s/,\s*}/}/g
:1i[<CR>
:$a]<Esc>
:1,$-1s/$/,/
\end{lstlisting}
然后再下载一个测试文件，结果如图\ref{编写脚本转换JSON}

\begin{figure}[H]
	\centering
	\includegraphics[width=0.48\linewidth]{assets/images/屏幕截图 2025-09-07 223644.png} \hfill
	\includegraphics[width=0.48\linewidth]{assets/images/屏幕截图 2025-09-07 224151.png}
	\caption{编写脚本转换JSON}
	\label{编写脚本转换JSON}
\end{figure}


